function SyncBufferTime(block)
%Syncs up the buffer to the expected data stream - making sure that the 'S'
% character is first, and the null terminator is last (29th) and that all
% CyberGlove data signals are properly represented in between. Takes as its
% input the data streaming from the device, and outputs the reorganized
% stream without the initial recognition or terminator bytes.
%
%%%% Original: ZCD Oct 09 
%%% Modified: Rajiv R Dec 09 %%% (Includes Time Stamp Info)
%


setup(block);

%% endfunction

function setup(block)

% Register number of ports
block.NumInputPorts  = 1;
block.NumOutputPorts = 3;

% Setup port properties to be inherited or dynamic
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;

% Override input port properties
block.InputPort(1).Dimensions  = 29;
block.InputPort(1).DatatypeID  = 0;  % double
block.InputPort(1).Complexity  = 'Real';
block.InputPort(1).DirectFeedthrough = true;

% Override output port properties
block.OutputPort(1).Dimensions  = 22;
block.OutputPort(1).DatatypeID  = 0; % double
block.OutputPort(1).Complexity  = 'Real';

block.OutputPort(2).Dimensions  = 1;
block.OutputPort(2).DatatypeID  = 8; % Boolean
block.OutputPort(2).Complexity  = 'Real';

block.OutputPort(3).Dimensions  = 1;
block.OutputPort(3).DatatypeID  = 0; % double
block.OutputPort(3).Complexity  = 'Real';

% Register parameters
block.NumDialogPrms     = 0;

% Register sample times
%  [0 offset]            : Continuous sample time
%  [positive_num offset] : Discrete sample time
%  [-1, 0]               : Inherited sample time
%  [-2, 0]               : Variable sample time
block.SampleTimes = [-1 0];


block.RegBlockMethod('PostPropagationSetup',    @DoPostPropSetup);
block.RegBlockMethod('InitializeConditions', @InitializeConditions);
block.RegBlockMethod('Start', @Start);
block.RegBlockMethod('Outputs', @Outputs);     % Required
block.RegBlockMethod('Update', @Update);
block.RegBlockMethod('Derivatives', @Derivatives);
block.RegBlockMethod('Terminate', @Terminate); % Required

% When a Level-2 M-file S-function with multiple output ports has dynamic
% sampling mode setting for any of its ports, it is necessary to register a
% 'SetInputPortSamplingMode' method.
block.RegBlockMethod('SetInputPortSamplingMode',@SetInputPortSamplingMode);

%% end setup

function SetInputPortSamplingMode(block,idx,fd)

block.InputPort(idx).SamplingMode = fd;

block.OutputPort(1).SamplingMode = fd;
block.OutputPort(2).SamplingMode = fd;
block.OutputPort(3).SamplingMode = fd;

%% end setinputportsampleingmode

function DoPostPropSetup(block)

%% end PostPropSetup

function InitializeConditions(block)

%% end InitializeConditions

function Start(block)

%% endfunction

function Outputs(block)

% The data stream is expected to initiate with the CyberGlove response,
% 'S', and terminate with the null character. If the buffer is out of sync
% we must search for the patern [null 'S'] and rearrange the data stream.

% This port flags the model to not update if the data vector is deemed
% corrupt. Our default assumption is that it is not corrupt.


if block.InputPort(1).Data(1)==83  &&  block.InputPort(1).Data(29)==0
    % If the data is sync'ed already
    databytes = block.InputPort(1).Data(2:23);
    timebytes = block.InputPort(1).Data(24:28);
    block.OutputPort(2).Data = boolean(1);
    % disp('Already sync''ed.')
else
    % search for the patern location
    ptrnInd = findstr(block.InputPort(1).Data',[0 83]);
    if isempty(ptrnInd)
        % if no such pattern exists this data stream is currputed, we don't
        % know what to do now
        databytes = block.InputPort(1).Data(2:23);
        timebytes = block.InputPort(1).Data(24:28);
        block.OutputPort(2).Data = boolean(0);
%         block.OutputPort(2).Data = boolean(0);  % issue corrupt flag
        % disp('Data stream corrupted.')
    else
        % we've located the pattern, now rearrange the vector
        if ptrnInd == 28
            % for the case where the pattern occurs at the very end of the
            % data stream, we must issue special commands to avoid errors
            databytes = block.InputPort(1).Data(1:22);
            timebytes = block.InputPort(1).Data(23:27);
            block.OutputPort(2).Data = boolean(1);
        else
            % in all other cases...
            sync = block.InputPort(1).Data( [ptrnInd+2:end, 1:ptrnInd-1] );
            databytes = sync(1:22);
            timebytes = sync(23:27);
            block.OutputPort(2).Data = boolean(1);
        end
    end
end
% attribute output
block.OutputPort(1).Data = databytes;
block.OutputPort(3).Data = decodetimestamp(timebytes);
%% end Outputs

function Update(block)

%% end Update

function Derivatives(block)

%% end Derivatives

function Terminate(block)

%% end Terminate

